package com.harmontronics.hanma.paas.paas.domain.tenant.service;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.harmontronics.hanma.paas.paas.consts.DbConstants;
import com.harmontronics.hanma.paas.paas.domain.tenant.repository.persistence.HmTenantAppRepository;
import com.harmontronics.hanma.paas.paas.domain.tenant.repository.po.HmTenantAppPO;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public
class DynamicDataSourceService implements InitializingBean {
    private static final Map<String, Long> LAST_VISIT_MILL = new ConcurrentHashMap<>();
    @Autowired
    private HmTenantAppRepository hmTenantAppRepository;
    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;

    /* 创建应用到连接池
     *
     * @param dbName
     * @return
     */
    public HikariDataSource createDataSource(String dsName,String dbName) {
        HikariDataSource dataSource = (HikariDataSource) dynamicRoutingDataSource.getDataSource(DbConstants.DS_MASTER_NAME);
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(getJdbcUrl(dataSource.getJdbcUrl(), dbName));
        config.setDriverClassName(dataSource.getDriverClassName());
        config.setUsername(dataSource.getUsername());
        config.setPassword(dataSource.getPassword());
        config.setMinimumIdle(0);
        config.setMaximumPoolSize(2);
        config.setMaxLifetime(dataSource.getMaxLifetime());
        config.setPoolName(dsName);
        return new HikariDataSource(config);
    }

    private String getJdbcUrl(String masterJdbcUrl, String dbName) {
        int lastIdx = masterJdbcUrl.lastIndexOf("/");
        String jdbcUrlPrefix = masterJdbcUrl.substring(0, lastIdx);
        return jdbcUrlPrefix + "/" + dbName;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
//        List<HmTenantAppPO> appPoList = hmTenantAppRepository.findApps();
//        for (HmTenantAppPO appPo : appPoList) {
//            try {
//                String dbName = "app_" + appPo.getAppUniqueId();
//                String dsName = "hm_" + appPo.getAppUniqueId();
//                HikariDataSource dataSource = createDataSource(dbName);
//                dynamicRoutingDataSource.addDataSource(dsName, dataSource);
//            } catch (Exception ex) {
//                ex.printStackTrace();
//            }
//        }
    }


    public DataSource createIfAbsent(String appUnique) {
        String dsName = "hm_" + appUnique;
        DataSource dataSource = getDatasourceNullIfAbsent(dsName);
        if (dataSource != null) {
            LAST_VISIT_MILL.put(dsName, System.currentTimeMillis());
            return dataSource;
        }
        synchronized (dsName) {
            dataSource = getDatasourceNullIfAbsent(dsName);
            if (dataSource != null) {
                LAST_VISIT_MILL.put(dsName, System.currentTimeMillis());
                return dataSource;
            }
            String dbName = "app_" + appUnique;
            HikariDataSource dataSource2 = createDataSource(dsName,dbName);
            addDataSource(dsName, dataSource2);
            return dataSource2;
        }
    }

    private DataSource getDatasourceNullIfAbsent(String dsName){
        HikariDataSource dataSource = (HikariDataSource) dynamicRoutingDataSource.getDataSource(dsName);
        //没找到会默认返回master
        if(dataSource == null || !dataSource.getPoolName().equals(dsName)){
            return null;
        }
        if (dataSource != null) {
            LAST_VISIT_MILL.put(dsName, System.currentTimeMillis());
        }

        return dataSource;
    }

    public void addDataSource(String dsName, DataSource dataSource) {
        dynamicRoutingDataSource.addDataSource(dsName, dataSource);
        LAST_VISIT_MILL.put(dsName, System.currentTimeMillis());
    }

    public void removeDataSource(String dsName) {
        dynamicRoutingDataSource.removeDataSource(dsName);
        LAST_VISIT_MILL.remove(dsName);
    }

    public DataSource getDataSource(String dsName) {
        DataSource dataSource = dynamicRoutingDataSource.getDataSource(dsName);
        return dataSource;
    }


    public void clean() {
        Iterator<Map.Entry<String, Long>> iterator = LAST_VISIT_MILL.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Long> entry = iterator.next();

            if (System.currentTimeMillis() - entry.getValue() > 30 * 60 * 1000) {
                DataSource dataSource = dynamicRoutingDataSource.getDataSource(entry.getKey());
                if (dataSource != null) {
                    dynamicRoutingDataSource.removeDataSource(entry.getKey());
                    ((HikariDataSource)dataSource).close();
                }
                iterator.remove();
            }
        }
    }
}
